package com.smarthome.common.tools.excel;

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

/**
 *  
 */
public abstract class AbstractReport {

    /**
     * 空字符
     */
    protected static final String NULL_STR = "";

    /**
     * The staring position of rows
     */
    protected int startRow = 1;

    /**
     * 当前类自己的logger
     */
    protected static Logger logger = Logger.getLogger(AbstractReport.class);

    protected void export(ReportHeader reportHeader, List<Object> reportDatas, OutputStream output) {
        HSSFWorkbook workBook = new HSSFWorkbook();
        exportExcel(workBook, reportHeader, reportDatas);
        // 开始导出Excel工作簿
        try {
            workBook.write(output);
            output.flush();
        } catch (IOException e1) {
            String msg = "开始导出Excel工作簿出现错误";
            logger.warn(msg);
        } finally {
            if (null != output) {
                try {
                    output.close();
                } catch (IOException e) {
                    String msg = "close out stream error";
                    logger.warn(msg);
                }
            }
        }

    }

    /**
     * 导出到excel工作薄
     * @param workBook
     * @param reportHeads
     * @param reportDatas
     */
    protected void exportExcel(HSSFWorkbook workBook, ReportHeader reportHeader, List<Object> reportDatas) {
        HSSFSheet sheet = exportHeader(workBook, reportHeader);
        exportDatas(workBook, reportHeader, reportDatas, sheet);
    }

    /**
     * 导出Excel表头
     * @param workBook
     * @param reportHeads
     * @return HSSFSheet
     */
    protected HSSFSheet exportHeader(HSSFWorkbook workBook, ReportHeader reportHeader) {
        List<String> tableHeader = getTableHeader();
        int cellNumber = getCellNumber();
        // 新建Excel表单
        HSSFSheet sheet = workBook.createSheet();

        if (null != reportHeader) {
            HSSFRow row = sheet.createRow(0);
            HSSFCell cell = null;
            for (int j = 0; j < cellNumber; j++) {
                cell = row.createCell((int) j);
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                // cell.setEncoding(HSSFCell.ENCODING_UTF_16);
                cell.setCellStyle(SheetStyle.getNormalHeaderStyle(workBook));
            }
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, (cellNumber - 1)));
            String cellValue = reportHeader.getDisplayName();
            if (cellValue == null) {
                cellValue = NULL_STR;
            }
            row.getCell((int) 0).setCellValue(cellValue);
        }
        HSSFRow row = sheet.createRow(null == reportHeader ? 0 : 1);
        for (int k = 0; k < cellNumber; k++) {
            HSSFCell headerCell = row.createCell((int) k);
            headerCell.setCellType(HSSFCell.CELL_TYPE_STRING);
            // headerCell.setEncoding(HSSFCell.ENCODING_UTF_16);
            headerCell.setCellValue(tableHeader.get(k));
        }
        return sheet;
    }

    /**
     * 设置表的列宽度
     * @param sheet
     * @param i
     * @param header
     */
    protected void formatTableColumns(HSSFSheet sheet, int i, ReportHeader header) {
        sheet.setColumnWidth((int) i, (int) header.getLength());
    }

    /**
     * 设置表的列宽度
     * @param sheet
     * @param i
     * @param header
     */
    protected void formatTableColumns(HSSFSheet sheet, int i, int length) {
        sheet.setColumnWidth((int) i, length);
    }

    /**
     * 设置表的列宽度
     * @param sheet
     * @param cols
     * @param header
     */
    protected void formatTableColumns(HSSFSheet sheet, int[] cols, ReportHeader header) {
        if (null == cols || cols.length == 0) {
            return;
        }
        for (int i = 0; i < cols.length; i++) {
            sheet.setColumnWidth((int) cols[i], (int) header.getLength());
        }

    }

    /**
     * 设置表的列宽度
     * @param sheet
     * @param cols
     * @param lengths
     */
    protected void formatTableColumns(HSSFSheet sheet, int[] cols, int[] lengths) {
        if (null == cols || cols.length == 0 || cols.length != lengths.length) {
            return;
        }
        for (int i = 0; i < cols.length; i++) {
            sheet.setColumnWidth((int) cols[i], lengths[i]);
        }

    }

    /**
     * 设置表的列宽度
     * @param sheet
     * @param cols
     * @param header
     */
    protected void formatTableColumns(HSSFSheet sheet, int[] cols, int length) {
        if (null == cols || cols.length == 0) {
            return;
        }
        for (int i = 0; i < cols.length; i++) {
            sheet.setColumnWidth((int) cols[i], length);
        }

    }

    /**
     * 返回tableHeader
     * <p>
     * @return </p>
     */
    protected abstract List<String> getTableHeader();

    /**
     * 返回cellNumber
     * <p>
     * @return </p>
     */
    protected abstract int getCellNumber();

    /**
     * 返回cellNumber
     * <p>
     * @return </p>
     */
    protected abstract List<String> getCells();

    /**
     * 导出reportDatas
     * @param workBook
     * @param reportHeads
     * @param reportDatas
     * @param sheet
     */
    protected void exportDatas(HSSFWorkbook workBook, ReportHeader reportHeader, List<Object> reportDatas, HSSFSheet sheet) {
        // 创建row行的开始
        int size = null == reportHeader ? 1 : 2;
        // 创建body数据开始
        sheet.setDefaultColumnWidth((int) 25);
        for (int i = 0; null != reportDatas && i < reportDatas.size(); i++) {
            Object obj = (Object) reportDatas.get(i);
            HSSFRow row = sheet.createRow((int) size + i);
            List<String> cells = getCells();
            for (int j = 0; j < cells.size(); j++) {
                HSSFCell cell = row.createCell((int) j);
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                // cell.setEncoding(HSSFCell.ENCODING_UTF_16);
                try {
                    cell.setCellValue(BeanUtils.getProperty(obj, cells.get(j)));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}